/*
# pymoz, Python extension for the Mozilla Toolkit
# Copyright (C) 2012 Malek Hadj-Ali
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef pyRuntime_h_
#define pyRuntime_h_


#include "pymoz.h"

#include "pyIRuntime.h"
#include "nsIObserver.h"

#include "nsIXPConnect.h"
#include "nsIJSContextStack.h"

#include "nsNetUtil.h"
#include "nsDataHashtable.h"
#include "nsClassHashtable.h"


class JSHolder
{
public:
    JSHolder(JSObject *jsobj);
    ~JSHolder();
    bool Hold();

    JSObject *mJSObj;
};


typedef nsDataHashtable<nsPtrHashKey<JSObject>, PyObject *> PyObjectCache;
typedef nsClassHashtable<nsPtrHashKey<PyObject>, JSHolder> JSObjectCache;


class pyRuntime : public pyIRuntime,
                  public nsIObserver
{
public:
    NS_DECL_ISUPPORTS
    NS_DECL_PYIRUNTIME
    NS_DECL_NSIOBSERVER

    static pyRuntime *GetService();

    static JSContext *GetJSContext();
    static PyObject *GetWindow();
    static bool SetException(PyObject *aExcValue);
    static bool ReportWarning(PyObject *aMessage, PyObject *aCategory,
                              PyObject *aFilename, PyObject *aLineno,
                              PyObject *aLine);
    static void ReportError();
    static bool HoldJSObject(JSObject **jsobj);
    static void DropJSObject(JSObject **jsobj);
    static bool ConvertChromeURL(const char *aSpec, nsACString& aPath);


    static PyObject *sError;
    static PyObject *sJSError;
    static PyObject *sXPCOMError;
    static PyObject *sJSWarning;
    static nsIThreadJSContextStack *sJSContextStack;
    static PyObjectCache *sPyCache;
    static JSObjectCache *sJSCache;

private:
    pyRuntime();
    ~pyRuntime();

    bool InitPython_Phase1();
    bool InitPython_Phase2();
    bool InitRuntime();
    bool InitWrappers();
    bool Initialize();
    void Finalize(bool final);

    already_AddRefed<nsIFile> GetFile(const nsACString& aSpec,
                                      const char *aOriginCharset,
                                      nsIURI *aBaseURI, char **path);
    bool UpdateWindow();


    static nsIXPConnect *sXPConnect;
    static nsresult sResult;
    static JSRuntime *sJSRuntime;

    static pyRuntime *sPyRuntime;
};


class JSAutoContextPusher
{
public:
    JSAutoContextPusher(JSContext *cx);
    ~JSAutoContextPusher();
};


#endif // pyRuntime_h_
